//! 验证工具

use regex::Regex;

/// 验证结果
#[derive(Debug, Clone, PartialEq)]
pub enum ValidationResult {
    /// 验证通过
    Valid,
    /// 验证失败，包含错误信息
    Invalid(String),
}

impl ValidationResult {
    /// 检查验证是否通过
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::ValidationResult;
    /// 
    /// let valid = ValidationResult::Valid;
    /// let invalid = ValidationResult::Invalid("错误信息".to_string());
    /// 
    /// assert_eq!(valid.is_valid(), true);
    /// assert_eq!(invalid.is_valid(), false);
    /// ```
    pub fn is_valid(&self) -> bool {
        match self {
            ValidationResult::Valid => true,
            ValidationResult::Invalid(_) => false,
        }
    }

    /// 获取错误信息（如果验证失败）
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::ValidationResult;
    /// 
    /// let valid = ValidationResult::Valid;
    /// let invalid = ValidationResult::Invalid("错误信息".to_string());
    /// 
    /// assert_eq!(valid.error_message(), None);
    /// assert_eq!(invalid.error_message(), Some(&"错误信息".to_string()));
    /// ```
    pub fn error_message(&self) -> Option<&String> {
        match self {
            ValidationResult::Valid => None,
            ValidationResult::Invalid(msg) => Some(msg),
        }
    }
}

/// 验证器 trait
pub trait Validator<T> {
    /// 验证给定的值
    fn validate(&self, value: &T) -> ValidationResult;
}

/// 电子邮件验证器
#[derive(Debug, Clone)]
pub struct EmailValidator;

impl Validator<String> for EmailValidator {
    /// 验证电子邮件地址
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{EmailValidator, Validator};
    /// 
    /// let validator = EmailValidator;
    /// 
    /// assert!(validator.validate(&"user@example.com".to_string()).is_valid());
    /// assert!(!validator.validate(&"invalid-email".to_string()).is_valid());
    /// ```
    fn validate(&self, email: &String) -> ValidationResult {
        // 基本的电子邮件验证正则表达式
        let email_regex = Regex::new(
            r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
        ).unwrap();

        if email_regex.is_match(email) {
            ValidationResult::Valid
        } else {
            ValidationResult::Invalid("无效的电子邮件地址".to_string())
        }
    }
}

/// 手机号码验证器（中国）
#[derive(Debug, Clone)]
pub struct PhoneNumberValidator;

impl Validator<String> for PhoneNumberValidator {
    /// 验证中国手机号码
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{PhoneNumberValidator, Validator};
    /// 
    /// let validator = PhoneNumberValidator;
    /// 
    /// assert!(validator.validate(&"13812345678".to_string()).is_valid());
    /// assert!(!validator.validate(&"12345".to_string()).is_valid());
    /// ```
    fn validate(&self, phone: &String) -> ValidationResult {
        // 中国手机号码验证正则表达式
        let phone_regex = Regex::new(r"^1[3-9]\d{9}$").unwrap();

        if phone_regex.is_match(phone) {
            ValidationResult::Valid
        } else {
            ValidationResult::Invalid("无效的手机号码".to_string())
        }
    }
}

/// 长度验证器
#[derive(Debug, Clone)]
pub struct LengthValidator {
    min_length: Option<usize>,
    max_length: Option<usize>,
}

impl LengthValidator {
    /// 创建一个新的长度验证器
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{LengthValidator, Validator};
    /// 
    /// let validator = LengthValidator::new().min(3).max(10);
    /// assert!(validator.validate(&"hello".to_string()).is_valid());
    /// assert!(!validator.validate(&"hi".to_string()).is_valid());
    /// ```
    pub fn new() -> Self {
        LengthValidator {
            min_length: None,
            max_length: None,
        }
    }

    /// 设置最小长度
    pub fn min(mut self, min: usize) -> Self {
        self.min_length = Some(min);
        self
    }

    /// 设置最大长度
    pub fn max(mut self, max: usize) -> Self {
        self.max_length = Some(max);
        self
    }
}

impl Validator<String> for LengthValidator {
    /// 验证字符串长度
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{LengthValidator, Validator};
    /// 
    /// let validator = LengthValidator::new().min(3).max(10);
    /// 
    /// assert!(validator.validate(&"hello".to_string()).is_valid());
    /// assert!(!validator.validate(&"hi".to_string()).is_valid());
    /// assert!(!validator.validate(&"this is a very long string".to_string()).is_valid());
    /// ```
    fn validate(&self, value: &String) -> ValidationResult {
        let len = value.len();
        
        if let Some(min) = self.min_length {
            if len < min {
                return ValidationResult::Invalid(format!("长度不能少于{}个字符", min));
            }
        }
        
        if let Some(max) = self.max_length {
            if len > max {
                return ValidationResult::Invalid(format!("长度不能超过{}个字符", max));
            }
        }
        
        ValidationResult::Valid
    }
}

/// 范围验证器
#[derive(Debug, Clone)]
pub struct RangeValidator<T> {
    min_value: Option<T>,
    max_value: Option<T>,
}

impl<T: PartialOrd + Copy + std::fmt::Display> RangeValidator<T> {
    /// 创建一个新的范围验证器
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{RangeValidator, Validator};
    /// 
    /// let validator = RangeValidator::new().min(1).max(100);
    /// assert!(validator.validate(&50).is_valid());
    /// assert!(!validator.validate(&150).is_valid());
    /// ```
    pub fn new() -> Self {
        RangeValidator {
            min_value: None,
            max_value: None,
        }
    }

    /// 设置最小值
    pub fn min(mut self, min: T) -> Self {
        self.min_value = Some(min);
        self
    }

    /// 设置最大值
    pub fn max(mut self, max: T) -> Self {
        self.max_value = Some(max);
        self
    }
}

impl<T: PartialOrd + Copy + std::fmt::Display> Validator<T> for RangeValidator<T> {
    /// 验证数值范围
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{RangeValidator, Validator};
    /// 
    /// let validator = RangeValidator::new().min(1).max(100);
    /// 
    /// assert!(validator.validate(&50).is_valid());
    /// assert!(!validator.validate(&0).is_valid());
    /// assert!(!validator.validate(&150).is_valid());
    /// ```
    fn validate(&self, value: &T) -> ValidationResult {
        if let Some(min) = self.min_value {
            if *value < min {
                return ValidationResult::Invalid(format!("值不能小于{}", min));
            }
        }
        
        if let Some(max) = self.max_value {
            if *value > max {
                return ValidationResult::Invalid(format!("值不能大于{}", max));
            }
        }
        
        ValidationResult::Valid
    }
}

/// 自定义验证器
#[derive(Debug, Clone)]
pub struct CustomValidator<F> {
    validator_fn: F,
    error_message: String,
}

impl<F> CustomValidator<F> {
    /// 创建一个自定义验证器
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{CustomValidator, Validator};
    /// 
    /// let validator = CustomValidator::new(
    ///     |s: &String| s.starts_with("A"),
    ///     "字符串必须以'A'开头".to_string()
    /// );
    /// 
    /// assert!(validator.validate(&"Apple".to_string()).is_valid());
    /// assert!(!validator.validate(&"Banana".to_string()).is_valid());
    /// ```
    pub fn new(validator_fn: F, error_message: String) -> Self {
        CustomValidator {
            validator_fn,
            error_message,
        }
    }
}

impl<F, T> Validator<T> for CustomValidator<F>
where
    F: Fn(&T) -> bool,
{
    /// 使用自定义函数验证
    fn validate(&self, value: &T) -> ValidationResult {
        if (self.validator_fn)(value) {
            ValidationResult::Valid
        } else {
            ValidationResult::Invalid(self.error_message.clone())
        }
    }
}

/// 组合验证器
pub struct CompositeValidator<T> {
    validators: Vec<Box<dyn Validator<T>>>,
}

impl<T> CompositeValidator<T> {
    /// 创建一个新的组合验证器
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::validation::{CompositeValidator, EmailValidator, LengthValidator, Validator};
    /// 
    /// let mut validator = CompositeValidator::new();
    /// validator.add_validator(Box::new(EmailValidator));
    /// validator.add_validator(Box::new(LengthValidator::new().min(5)));
    /// 
    /// assert!(validator.validate(&"user@example.com".to_string()).is_valid());
    /// ```
    pub fn new() -> Self {
        CompositeValidator {
            validators: Vec::new(),
        }
    }

    /// 添加验证器
    pub fn add_validator(&mut self, validator: Box<dyn Validator<T>>) {
        self.validators.push(validator);
    }
}

impl<T> Validator<T> for CompositeValidator<T> {
    /// 使用所有验证器进行验证
    fn validate(&self, value: &T) -> ValidationResult {
        for validator in &self.validators {
            let result = validator.validate(value);
            if !result.is_valid() {
                return result;
            }
        }
        ValidationResult::Valid
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_validation_result() {
        let valid = ValidationResult::Valid;
        let invalid = ValidationResult::Invalid("错误信息".to_string());

        assert_eq!(valid.is_valid(), true);
        assert_eq!(invalid.is_valid(), false);
        assert_eq!(valid.error_message(), None);
        assert_eq!(invalid.error_message(), Some(&"错误信息".to_string()));
    }

    #[test]
    fn test_email_validator() {
        let validator = EmailValidator;

        assert!(validator.validate(&"user@example.com".to_string()).is_valid());
        assert!(validator.validate(&"test.email+tag@domain.co.uk".to_string()).is_valid());
        assert!(!validator.validate(&"invalid-email".to_string()).is_valid());
        assert!(!validator.validate(&"@example.com".to_string()).is_valid());
        assert!(!validator.validate(&"user@".to_string()).is_valid());
    }

    #[test]
    fn test_phone_number_validator() {
        let validator = PhoneNumberValidator;

        assert!(validator.validate(&"13812345678".to_string()).is_valid());
        assert!(validator.validate(&"15912345678".to_string()).is_valid());
        assert!(!validator.validate(&"12345".to_string()).is_valid());
        assert!(!validator.validate(&"123456789012".to_string()).is_valid());
        assert!(!validator.validate(&"23812345678".to_string()).is_valid());
    }

    #[test]
    fn test_length_validator() {
        let validator = LengthValidator::new().min(3).max(10);

        assert!(validator.validate(&"hello".to_string()).is_valid());
        assert!(!validator.validate(&"hi".to_string()).is_valid());
        assert!(!validator.validate(&"this is a very long string".to_string()).is_valid());
    }

    #[test]
    fn test_range_validator() {
        let validator = RangeValidator::new().min(1).max(100);

        assert!(validator.validate(&50).is_valid());
        assert!(!validator.validate(&0).is_valid());
        assert!(!validator.validate(&150).is_valid());
    }

    #[test]
    fn test_custom_validator() {
        let validator = CustomValidator::new(
            |s: &String| s.starts_with("A"),
            "字符串必须以'A'开头".to_string()
        );

        assert!(validator.validate(&"Apple".to_string()).is_valid());
        assert!(!validator.validate(&"Banana".to_string()).is_valid());
    }

    #[test]
    fn test_composite_validator() {
        let mut validator = CompositeValidator::new();
        validator.add_validator(Box::new(EmailValidator));
        validator.add_validator(Box::new(LengthValidator::new().min(5)));

        assert!(validator.validate(&"user@example.com".to_string()).is_valid());
        assert!(validator.validate(&"us@x.c".to_string()).is_valid()); // 长度为6，应该通过长度验证
        assert!(!validator.validate(&"invalid-email".to_string()).is_valid());
    }
}